
package com.jf.cloud.product.controller.app;

import cn.hutool.core.collection.CollUtil;
import com.jf.cloud.api.auth.bo.UserInfoInTokenBO;
import com.jf.cloud.api.combo.feign.ComboFeignClient;
import com.jf.cloud.api.delivery.feign.DeliveryFeignClient;
import com.jf.cloud.api.feign.SearchSpuFeignClient;
import com.jf.cloud.api.multishop.constant.ShopStatus;
import com.jf.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.jf.cloud.api.product.util.ProductLangUtil;
import com.jf.cloud.api.vo.EsPageVO;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.product.constant.PreSaleType;
import com.jf.cloud.common.product.constant.SpuType;
import com.jf.cloud.common.product.constant.SupplierDeliveryType;
import com.jf.cloud.common.product.constant.SupplierSpuType;
import com.jf.cloud.common.product.dto.ProductSearchDTO;
import com.jf.cloud.common.product.dto.SpuDTO;
import com.jf.cloud.common.product.vo.*;
import com.jf.cloud.common.product.vo.app.SkuAppVO;
import com.jf.cloud.common.product.vo.app.SpuAppVO;
import com.jf.cloud.common.product.vo.search.ProductSearchVO;
import com.jf.cloud.common.product.vo.search.SpuSearchVO;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.common.util.Json;
import com.jf.cloud.common.util.PriceUtil;
import com.jf.cloud.product.model.SpuConsignmentChange;
import com.jf.cloud.product.model.SpuExtension;
import com.jf.cloud.product.service.*;
import com.jf.cloud.product.vo.SkuStockVO;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import ma.glasnost.orika.MapperFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * spu信息
 *
 * @author zz
 * @date 2020-10-28 15:27:24
 */
@RestController("appSpuController")
@RequestMapping("/ma/spu")
@Tag(name = "app-spu信息")
public class SpuController {
    private static final Logger logger = LoggerFactory.getLogger(SpuController.class);
    @Autowired
    private SpuService spuService;
    @Autowired
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private SkuService skuService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SpuBrowseLogService spuBrowseLogService;
    @Autowired
    private ShopDetailFeignClient shopDetailFeignClient;
    @Autowired
    private SpuConsignmentChangeService spuConsignmentChangeService;
    @Autowired
    private ComboFeignClient comboFeignClient;
    @Autowired
    private GiveawayService giveawayService;
    @Autowired
    private DeliveryFeignClient deliveryFeignClient;
    @Autowired
    private SkuStockService skuStockService;
    @Autowired
    private MapperFacade mapperFacade;

    @GetMapping("/prod_info")
    @Operation(summary = "商品详情信息" , description = "根据商品ID（prodId）获取商品信息")
    @Parameters({
            @Parameter(name = "spuId", description = "商品ID" , required = true),
            @Parameter(name = "userId", description = "用户id"),
            @Parameter(name = "addrId", description = "用户地址id")
    })
    public ServerResponseEntity<SpuAppVO> prodInfo(@RequestParam("spuId") Long spuId,
                                                   @RequestParam(value = "userId",required = false) Long userId,
                                                   @RequestParam(value = "addrId", required = false) Long addrId) {
        SpuAppVO spu = spuService.prodInfo(spuId);
        if (Objects.equals(spu.getSpuType(), SpuType.SCORE.value())) {
            throw new LuckException(ResponseEnum.SPU_NOT_EXIST);
        }
        // 插入商品和sku库存信息
        this.setSpuAndSkuStock(spu);
        // spu活动列表
        spu.setSpuActivity(spuService.spuActivityBySpuId(spu.getShopId(), spuId));
        //获取赠品信息
        GiveawayVO giveawayVO = giveawayService.getGiveawaySpuBySpuId(spuId);
        spu.setGiveaway(giveawayVO);
        // 供应商商品信息处理
        disposeSpuMsg(spu);
        //获取商品套餐信息
        List<ComboVO> comboVOS = comboFeignClient.comboVoListBySpuId(spuId).getData();
        if (Objects.nonNull(comboVOS)){
            spu.setComboList(comboVOS);
        }
        // 处理下商品和sku的预售,计算定金按比例收取的预售商品实际定金数额
        handlePreSaleInfo(spu);
        // 判断是否在配送范围内
        boolean deliverable = Objects.equals(spu.getSpuType(), SpuType.ACTIVE.value())
                || Objects.equals(spu.getSpuMold(), 1)
                || Objects.isNull(userId);
        if(deliverable){
            spu.setIsDelivery(true);
            logger.info("prodInfo-用户地址id为空XXXXXXXXXXXXXXXXX");
        } else {
            ServerResponseEntity<Boolean> booleanServerResponseEntity;
            Long deliveryTemplateId = Objects.nonNull(spu.getDeliveryTemplateId()) ? spu.getDeliveryTemplateId() : 0L;
            // TO用户i地址id为空，则检查用户默认地址的配送范围
            if (addrId == null || addrId == 0) {
                logger.info("prodInfo-用户地址id为空, spuId:{}, deliveryTemplateId:{}", spuId, deliveryTemplateId);
                booleanServerResponseEntity = deliveryFeignClient.checkAddr(deliveryTemplateId, userId, 0L);
            } else {
                logger.info("prodInfo-有用户地址, spuId:{}, deliveryTemplateId:{}", spuId, deliveryTemplateId);
                booleanServerResponseEntity = deliveryFeignClient.checkDeliveryRange(deliveryTemplateId, addrId);
            }
            if (booleanServerResponseEntity.isFail()){
                throw new LuckException(booleanServerResponseEntity.getMsg());
            }
            spu.setIsDelivery(booleanServerResponseEntity.getData());
        }
        return ServerResponseEntity.success(spu);
    }


    private void setSpuAndSkuStock(SpuAppVO spu) {
        // 因为库存的缓存是经常变的，而规格信息的缓存是几乎不变的，所以库存的缓存要独立拿出来
        SpuExtension spuExtension = spuService.getSpuExtension(spu.getSpuId());
        spu.setCommentNum(spuExtension.getCommentNum());

        Integer totalStock = 0;
        List<SkuStockVO> skuStocks;
        boolean supplierDelivery = Objects.nonNull(spu.getSupplierSpuType()) && Objects.equals(spu.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value());
        if (supplierDelivery) {
            // 供应商商品库存
            totalStock = skuStockService.getTotalBySpuId(spu.getSupplierSpuId());
            //供应商SKU库存
            skuStocks = skuStockService.listStockBySpuId(spu.getSupplierSpuId());
        } else {
            //商家自己库存
            totalStock = skuStockService.getTotalBySpuId(spu.getSpuId());
            skuStocks = skuStockService.listStockBySpuId(spu.getSpuId());
        }
        if (Objects.nonNull(totalStock)) {
            spu.setTotalStock(totalStock);
        }
        Map<Long, Integer> skuStock = skuStocks.stream().collect(Collectors.toMap(SkuStockVO::getSkuId, SkuStockVO::getStock));
        for (SkuAppVO sku : spu.getSkus()) {
            // 从map中插入sku库存
            if (supplierDelivery) {
                sku.setStock(skuStock.get(sku.getSupplierSkuId()));
                sku.setSupplierStock(skuStock.get(sku.getSupplierSkuId()));
            } else {
                sku.setStock(skuStock.get(sku.getSkuId()));
            }
            if (Objects.isNull(sku.getStock())) {
                sku.setStock(0);
            }
        }
    }
    private void handlePreSaleInfo(SpuAppVO spuAppVO) {
        if (!Objects.equals(spuAppVO.getPreSaleType(), PreSaleType.DEPOSIT.value())){
            return;
        }
        for (SkuAppVO sku : spuAppVO.getSkus()) {
            sku.setDepositAmount(spuAppVO.getDepositAmount());
            sku.setDepositExpansionAmount(spuAppVO.getDepositExpansionAmount());
        }
        if(Objects.equals(spuAppVO.getDepositType(), 0)){
            Long depositAmount = PriceUtil.divideByBankerRoundingThan(spuAppVO.getPriceFee() * spuAppVO.getDepositAmount(), 10000, false);
            Long depositExpansionAmount = PriceUtil.divideByBankerRoundingThan(spuAppVO.getPriceFee() * spuAppVO.getDepositExpansionAmount(), 10000, false);
            for (SkuAppVO sku : spuAppVO.getSkus()) {
                Long skuDepositAmount = PriceUtil.divideByBankerRoundingThan(sku.getPriceFee() * spuAppVO.getDepositAmount(), 10000, false);
                Long skuDepositExpansionAmount = PriceUtil.divideByBankerRoundingThan(sku.getPriceFee() * spuAppVO.getDepositExpansionAmount(), 10000, false);
                sku.setDepositAmount(skuDepositAmount);
                sku.setDepositExpansionAmount(skuDepositExpansionAmount);
            }
            spuAppVO.setDepositAmount(depositAmount);
            spuAppVO.setDepositExpansionAmount(depositExpansionAmount);
        }
    }

    /**
     * 处理套配商品
     * @param comboVOS
     */
    private void disposeMatchSpu(List<ComboVO> comboVOS){
        Map<Long, List<ComboVO>> comboVoByComboId = comboVOS.stream().collect(Collectors.groupingBy(ComboVO::getComboId));
        for (ComboVO comboVO : comboVOS) {
            List<ComboSpuVO> matchingSpuS = comboVO.getMatchingSpus();
            List<Long> spuIdList = matchingSpuS.stream().map(e -> e.getSpuId()).collect(Collectors.toList());
            //获取商品基本信息
            List<SpuVO> spuVOList = spuService.listSpuBySpuIds(spuIdList);
            //根据商品id分组
            Map<Long, List<SpuVO>> spuVoBySpuId = spuVOList.stream().collect(Collectors.groupingBy(SpuVO::getSpuId));
            for (ComboSpuVO spuVO : matchingSpuS) {
                SpuVO vo = spuVoBySpuId.get(spuVO.getSpuId()).get(0);
                spuVO.setSpuName(vo.getName());
                spuVO.setPic(vo.getMainImgUrl());
                spuVO.setSpuStatus(vo.getStatus());
            }
        }

    }
    private List<SkuAppVO> isFiltrationDisableAndDeleted(SpuAppVO spuAppVO, List<SkuAppVO> skuAppVOS) {
        if (Objects.equals(spuAppVO.getSupplierDeliveryType(), SupplierDeliveryType.SHOP_DELIVERY.value())) {
            //商家自行发货不用过滤
            return skuAppVOS;
        }
        //获取供应商商品spu
        SpuVO spupplierSpu = spuService.getBySpuId(spuAppVO.getSupplierSpuId());
        spuAppVO.setDeliveryTemplateId(spupplierSpu.getDeliveryTemplateId());
        //获取供应商品sku
        List<SkuVO> skuVOS = skuService.listSkuWithAttrBySpuId(spuAppVO.getSupplierSpuId());
        Map<Long, Integer> skuStatus = skuVOS.stream().collect(Collectors.toMap(SkuVO::getSkuId, SkuVO::getStatus));
        Iterator<SkuAppVO> skuAppVOIterator = skuAppVOS.iterator();
        while (skuAppVOIterator.hasNext()) {
            Integer status = skuStatus.get(skuAppVOIterator.next().getSupplierSkuId());
            if (Objects.equals(status, 0) || Objects.equals(status, -1) || Objects.equals(status, null)) {
                skuAppVOIterator.remove();
            }
        }
        return skuAppVOS;

    }

    /**
     * 处理代销商品信息
     *
     * @param spuVO
     * @return
     */
    private void disposeSpuMsg(SpuAppVO spuVO) {
        Long spuId = spuVO.getSpuId();
        //获取代销商品基本信息是否改变
        SpuConsignmentChange spuConsignmentChange = spuConsignmentChangeService.getBySpuId(spuId);
        if (Objects.isNull(spuConsignmentChange)){
            return ;
        }
        //获取供应商信息
        SpuVO supplierSpu = spuService.getBySpuId(spuVO.getSupplierSpuId());
        ProductLangUtil.spu(supplierSpu);
        //名称
        if (Objects.equals(spuConsignmentChange.getNameChange(), 0)) {
            if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setSpuName(supplierSpu.getName());
            }
        }
        //图片
        if (Objects.equals(spuConsignmentChange.getImageChange(), 0)) {
            if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setImgUrls(supplierSpu.getImgUrls());
                spuVO.setMainImgUrl(supplierSpu.getMainImgUrl());
            }
        }
        //视频
        if (Objects.equals(spuConsignmentChange.getVideoChange(), 0)) {
            if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setVideo(supplierSpu.getVideo());
            }
        }
        //卖点
        if (Objects.equals(spuConsignmentChange.getSellingPointChange(), 0)) {
            if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setSellingPoint(supplierSpu.getSellingPoint());
            }
        }
        //计量单位
        if (Objects.equals(spuConsignmentChange.getMeasureUnitChange(), 0)) {
            if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setMeasureUnit(supplierSpu.getMeasureUnit());
            }
        }
        //spuCod
        if (Objects.equals(spuConsignmentChange.getSpuCodeChange(), 0)) {
            if (Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setSpuCode(supplierSpu.getSpuCode());
            }
        }
        //详情描述
        if (Objects.equals(spuConsignmentChange.getDetailChange(), 0) && Objects.equals(spuVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())) {
                spuVO.setDetail(CollUtil.isEmpty(supplierSpu.getDetailList()) ? null : supplierSpu.getDetailList().get(0).getDetail());
        }
    }

    @GetMapping("/score_prod_info")
    @Operation(summary = "积分商品详情信息" , description = "根据商品ID（prodId）获取积分商品信息")
    @Parameter(name = "spuId", description = "商品ID" , required = true)
    public ServerResponseEntity<SpuAppVO> scoreProdInfo(@RequestParam("spuId") Long spuId) {
        SpuAppVO spuAppVO = spuService.prodInfo(spuId);
        if (!Objects.equals(spuAppVO.getSpuType(), SpuType.SCORE.value())) {
            throw new LuckException(ResponseEnum.SPU_NOT_EXIST);
        }
        SpuVO spuVO = mapperFacade.map(spuAppVO, SpuVO.class);
        List<SkuAppVO> skuAppVO = skuService.getSpuDetailSkuInfo(spuVO);
        spuAppVO.setSkus(skuAppVO);
        return ServerResponseEntity.success(spuAppVO);
    }

    @GetMapping("/sku_list")
    @Operation(summary = "sku信息" , description = "根据商品ID（prodId）单独获取sku信息")
    @Parameter(name = "spuId", description = "商品ID" , required = true)
    public ServerResponseEntity<List<SkuAppVO>> skuList(@RequestParam("spuId") Long spuId) {
        SpuVO spuVO = spuService.getBySpuId(spuId);
        List<SkuAppVO> skuList = skuService.getSpuDetailSkuInfo(spuVO);

        return ServerResponseEntity.success(skuList);
    }

    @GetMapping("/recommend_list")
    @Operation(summary = "推荐商品列表" , description = "根据商品ID（prodId）获取商品信息")
    public ServerResponseEntity<EsPageVO<ProductSearchVO>> recommendList(PageDTO pageDTO, SpuDTO spuDTO) {
        UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
        ProductSearchDTO productSearch = new ProductSearchDTO();
        Long primaryCategoryId = null;
        if (Objects.isNull(spuDTO.getSpuType())) {
            spuDTO.setSpuType(SpuType.NORMAL.value());
        }
        // 已登陆
        if (Objects.nonNull(userInfoInTokenBO)) {
            primaryCategoryId = spuBrowseLogService.recommendCategoryId(spuDTO.getSpuType());
        }
        // 已登陆但还没有数据，或未登陆
        boolean serCategoryId = (!Objects.equals(spuDTO.getSpuType(), SpuType.SCORE.value()) && Objects.isNull(primaryCategoryId)) && Objects.nonNull(spuDTO.getCategoryId());
        if (serCategoryId) {
            try {
                CategoryVO category = categoryService.getByCategoryId(spuDTO.getCategoryId());
                if (Objects.nonNull(category)) {
                    primaryCategoryId = category.getPrimaryCategoryId();
                }
            } catch (Exception e) {
                logger.error("推荐商品列表错误：{}", e);
            }
        }
        //如果有商品id则过滤掉
        if (Objects.nonNull(spuDTO.getSpuId())) {
            List<Long> spuIds = new ArrayList<>();
            spuIds.add(spuDTO.getSpuId());
            productSearch.setSpuIdsExclude(spuIds);
        }
        ServerResponseEntity<List<Long>> shopEntity = shopDetailFeignClient.getShopIdsByShopStatus(ShopStatus.OPEN.value());
        if (!shopEntity.isSuccess()) {
            throw new LuckException(shopEntity.getMsg());
        }
        List<Long> shopIds = shopEntity.getData();
        // 营业中的商家id
        if (CollUtil.isNotEmpty(shopIds)) {
            productSearch.setShopIds(shopIds);
        }
        productSearch.setPrimaryCategoryId(primaryCategoryId);
        productSearch.setPageNum(pageDTO.getPageNum());
        productSearch.setPageSize(pageDTO.getPageSize());
        productSearch.setSpuType(spuDTO.getSpuType());
        if(Objects.nonNull(spuDTO.getShopAddr())){
            productSearch.setShopAddr(spuDTO.getShopAddr());
        }
        ServerResponseEntity<EsPageVO<ProductSearchVO>> spuResponseEntity = searchSpuFeignClient.search(productSearch);
        if (spuResponseEntity.isFail()) {
            throw new LuckException(spuResponseEntity.getMsg());
        }
        EsPageVO<ProductSearchVO> data = spuResponseEntity.getData();
        Integer size = pageDTO.getPageSize();
        int spuNum = data.getList().get(0).getSpus().size();
        // 推荐商品的数量不足时，查询额外的商品进行填充
        if (size > spuNum) {
            productSearch.setPageSize(Math.toIntExact(size - spuNum));
            productSearch.setPageNum(1);
            // 查询该分类以外的商品
            productSearch.setPrimaryCategoryId(null);
            productSearch.setNotPrimaryCategoryId(primaryCategoryId);
            ServerResponseEntity<EsPageVO<ProductSearchVO>> addSpuResponseEntity = searchSpuFeignClient.search(productSearch);
            if (addSpuResponseEntity.isFail()) {
                throw new LuckException(addSpuResponseEntity.getMsg());
            }
            for (ProductSearchVO productSearchVO : addSpuResponseEntity.getData().getList()) {
                if (CollUtil.isNotEmpty(productSearchVO.getSpus())) {
                    Map<Long, SpuSearchVO> spuMap = data.getList().get(0).getSpus().stream().collect(Collectors.toMap(SpuSearchVO::getSpuId, s -> s));
                    Map<Long, SpuSearchVO> spusMap = productSearchVO.getSpus().stream().collect(Collectors.toMap(SpuSearchVO::getSpuId, s -> s));
                    List<SpuSearchVO> addSpus = new ArrayList<>();
                    for (Map.Entry<Long, SpuSearchVO> entry : spusMap.entrySet()) {
                        if(!spuMap.containsKey(entry.getKey())){
                            addSpus.add(entry.getValue());
                        }
                    }
                    // 取并集
                    data.getList().get(0).getSpus().addAll(addSpus);
                }
            }
            data.setTotal((long) data.getList().get(0).getSpus().size());
            data.setPages(data.getTotal() > 0 ? pageDTO.getPageNum() : 0);
        }
        List<SpuSearchVO> list = data.getList().get(0).getSpus().stream().filter(productSearchVO -> Objects.equals(productSearchVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())).collect(Collectors.toList());
        List<Long> supplierSpuIds = list.stream().map(SpuSearchVO::getSupplierSpuId).collect(Collectors.toList());
        if(CollUtil.isNotEmpty(supplierSpuIds)){
            List<SpuVO> supplierSpus = spuService.getBySpuIds(supplierSpuIds);
            Map<Long, SpuVO> supplierSpuMap = supplierSpus.stream().collect(Collectors.toMap(SpuVO::getSpuId, spu -> spu));
            for(SpuSearchVO spuSearchVO : data.getList().get(0).getSpus()){
                if(Objects.equals(spuSearchVO.getSupplierDeliveryType(), SupplierDeliveryType.SUPPLIER_DELIVERY.value())){
                    spuSearchVO.setSpuName(supplierSpuMap.get(spuSearchVO.getSupplierSpuId()).getName());
                }
            }
        }

        return spuResponseEntity;
    }
}
